/******************************************************
*  Copyright(c) pages.ilovezxl.top
*  FileName :thread.c
*  Author : rivulet.dave
*  Description : 系统内核
*  Data : 2019-04-23
******************************************************/

/*********************************************************************
 * INCLUDES
 */

#include "stdrope.h"
#include "sallib.h"
#include "salagent.h"

#include "thread.h"

#if (SAL_PRODUCER == _SAL_LINUX_)
#include "thread_linux.h"
#endif

/*********************************************************************
 *  EXTERNAL VARIABLES
 */

/*********************************************************************
 * MACROS
 */

/*********************************************************************
 * TYPES
 */

typedef struct _os_info
{
    MOD_INFO_S  stMod;
    osVersion_t stOSVer;
} OS_INFO_S;

/*********************************************************************
 * FUNCTIONS DECLARE
 */


/*********************************************************************
 *  VARIABLES
 */

static OS_INFO_S s_stOSInfo = 
{
    {
        .uiModID = OS_THREAD,
        .pName = TOSTR(OS_THREAD),
    },
    {
        .api = 0x00000001,
        .kernel = 0x00000001,
    },
};
static OS_THREAD_BASE_S *s_pstOSThreadObject = NULL;

/*********************************************************************
 * FUNCTIONS
 */

/**
 *   @Description: 系统模块安装
 *   @param : NA
 *   @return: _OK/_ERR
 */
int32_t osInstall(void)
{
#if (SAL_PRODUCER == _SAL_LINUX_)
    s_pstOSThreadObject = osThreadLinuxObjNew();
#endif
    return osOK;
}

/**
 *   @Description: 系统模块卸载
 *   @param : NA
 *   @return: _OK/_ERR
 */
int32_t osUninstall(void)
{
#if (SAL_PRODUCER == _SAL_LINUX_)
    s_pstOSThreadObject = NULL;
#endif
    return osOK;
}

//  ==== Kernel Management Functions ====
 
/// Initialize the RTOS Kernel.
/// \return status code that indicates the execution status of the function.
osStatus_t osKernelInitialize (void)
{
    if (!s_pstOSThreadObject)
    {
        return osError;
    }

    if (!s_pstOSThreadObject->pfOSKernelInitialize)
    {
        return osOK;
    }

    return s_pstOSThreadObject->pfOSKernelInitialize();
}
 
///  Get RTOS Kernel Information.
/// \param[out]    version       pointer to buffer for retrieving version information.
/// \param[out]    id_buf        pointer to buffer for retrieving kernel identification string.
/// \param[in]     id_size       size of buffer for kernel identification string.
/// \return status code that indicates the execution status of the function.
osStatus_t osKernelGetInfo (osVersion_t *version, char *id_buf, uint32_t id_size)
{
    osStatus_t iRet;

    if (!s_pstOSThreadObject || !version)
    {
        return osError;
    }

    if (!s_pstOSThreadObject->pfOSKernelGetInfo)
    {
        return osOK;
    }

    iRet = s_pstOSThreadObject->pfOSKernelGetInfo(version, id_buf, id_size);
    s_stOSInfo.stOSVer.api = version->api;
    s_stOSInfo.stOSVer.kernel = version->kernel;
    return iRet;
}

/// Get the current RTOS Kernel state.
/// \return current RTOS Kernel state.
osKernelState_t osKernelGetState (void)
{
    if (!s_pstOSThreadObject)
    {
        return osKernelInactive;
    }

    if (!s_pstOSThreadObject->pfOSKernelGetState)
    {
        return osKernelInactive;
    }

    return s_pstOSThreadObject->pfOSKernelGetState();
}

/// Start the RTOS Kernel scheduler.
/// \return status code that indicates the execution status of the function.
osStatus_t osKernelStart (void)
{
    if (!s_pstOSThreadObject)
    {
        return osError;
    }

    if (!s_pstOSThreadObject->pfOSKernelStart)
    {
        return osOK;
    }

    return s_pstOSThreadObject->pfOSKernelStart();
}
 
/// Lock the RTOS Kernel scheduler.
/// \return previous lock state (1 - locked, 0 - not locked, error code if negative).
int32_t osKernelLock (void)
{
    if (!s_pstOSThreadObject)
    {
        return -1;
    }

    if (!s_pstOSThreadObject->pfOSKernelLock)
    {
        return 0;
    }

    return s_pstOSThreadObject->pfOSKernelLock();
}
 
/// Unlock the RTOS Kernel scheduler.
/// \return previous lock state (1 - locked, 0 - not locked, error code if negative).
int32_t osKernelUnlock (void)
{
    if (!s_pstOSThreadObject)
    {
        return -1;
    }

    if (!s_pstOSThreadObject->pfOSKernelUnlock)
    {
        return 0;
    }

    return s_pstOSThreadObject->pfOSKernelUnlock();
}
 
/// Restore the RTOS Kernel scheduler lock state.
/// \param[in]     lock          lock state obtained by \ref osKernelLock or \ref osKernelUnlock.
/// \return new lock state (1 - locked, 0 - not locked, error code if negative).
int32_t osKernelRestoreLock (int32_t lock)
{
    if (!s_pstOSThreadObject)
    {
        return -1;
    }

    if (!s_pstOSThreadObject->pfOSKernelRestoreLock)
    {
        return 0;
    }

    return s_pstOSThreadObject->pfOSKernelRestoreLock(lock);
}
 
/// Suspend the RTOS Kernel scheduler.
/// \return time in ticks, for how long the system can sleep or power-down.
uint32_t osKernelSuspend (void)
{
    if (!s_pstOSThreadObject)
    {
        return -1;
    }

    if (!s_pstOSThreadObject->pfOSKernelSuspend)
    {
        return 0;
    }

    return s_pstOSThreadObject->pfOSKernelSuspend();
}
 
/// Resume the RTOS Kernel scheduler.
/// \param[in]     sleep_ticks   time in ticks for how long the system was in sleep or power-down mode.
void osKernelResume (uint32_t sleep_ticks)
{
    if (!s_pstOSThreadObject || !s_pstOSThreadObject->pfOSKernelResume)
    {
        return;
    }

    s_pstOSThreadObject->pfOSKernelResume(sleep_ticks);
}

/// Get the RTOS kernel tick count.
/// \return RTOS kernel current tick count.
uint32_t osKernelGetTickCount (void)
{
    if (!s_pstOSThreadObject || !s_pstOSThreadObject->pfOSKernelGetTickCount)
    {
        return 0;
    }
    return s_pstOSThreadObject->pfOSKernelGetTickCount();
}

/// Get the RTOS kernel tick frequency.
/// \return frequency of the kernel tick in hertz, i.e. kernel ticks per second.
uint32_t osKernelGetTickFreq (void)
{
    if (!s_pstOSThreadObject || !s_pstOSThreadObject->pfOSKernelGetTickFreq)
    {
        return 0;
    }
    return s_pstOSThreadObject->pfOSKernelGetTickFreq();
}

/// Get the RTOS kernel system timer count.
/// \return RTOS kernel current system timer count as 32-bit value.
uint32_t osKernelGetSysTimerCount (void)
{
    if (!s_pstOSThreadObject || !s_pstOSThreadObject->pfOSKernelGetSysTimerCount)
    {
        return 0;
    }
    return s_pstOSThreadObject->pfOSKernelGetSysTimerCount();
}
 
/// Get the RTOS kernel system timer frequency.
/// \return frequency of the system timer in hertz, i.e. timer ticks per second.
uint32_t osKernelGetSysTimerFreq (void)
{
    if (!s_pstOSThreadObject || !s_pstOSThreadObject->pfOSKernelGetSysTimerFreq)
    {
        return 0;
    }
    return s_pstOSThreadObject->pfOSKernelGetSysTimerFreq();
}
 
 
//  ==== Thread Management Functions ====
 
/// Create a thread and add it to Active Threads.
/// \param[in]     func          thread function.
/// \param[in]     argument      pointer that is passed to the thread function as start argument.
/// \param[in]     attr          thread attributes; NULL: default values.
/// \return thread ID for reference by other functions or NULL in case of error.
osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr)
{
    if (!s_pstOSThreadObject || !s_pstOSThreadObject->pfOSThreadNew)
    {
        return NULL;
    }
    return s_pstOSThreadObject->pfOSThreadNew(func, argument, attr);
}
 
/// Get name of a thread.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return name as null-terminated string.
const char *osThreadGetName (osThreadId_t thread_id)
{
    if (!s_pstOSThreadObject || !s_pstOSThreadObject->pfOSThreadGetName)
    {
        return "unknow";
    }
    return s_pstOSThreadObject->pfOSThreadGetName(thread_id);
}
 
/// Return the thread ID of the current running thread.
/// \return thread ID for reference by other functions or NULL in case of error.
osThreadId_t osThreadGetId (void)
{
    if (!s_pstOSThreadObject || !s_pstOSThreadObject->pfOSThreadGetId)
    {
        return NULL;
    }
    return s_pstOSThreadObject->pfOSThreadGetId();
}
 
/// Get current thread state of a thread.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return current thread state of the specified thread.
osThreadState_t osThreadGetState (osThreadId_t thread_id)
{
    return osKernelInactive;
}
 
/// Get stack size of a thread.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return stack size in bytes.
uint32_t osThreadGetStackSize (osThreadId_t thread_id)
{
    if (!s_pstOSThreadObject || !s_pstOSThreadObject->pfOSThreadGetStackSize)
    {
        return 0;
    }
    return s_pstOSThreadObject->pfOSThreadGetStackSize(thread_id);
}
 
/// Get available stack space of a thread based on stack watermark recording during execution.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return remaining stack space in bytes.
uint32_t osThreadGetStackSpace (osThreadId_t thread_id)
{
    if (!s_pstOSThreadObject || !s_pstOSThreadObject->pfOSThreadGetStackSpace)
    {
        return 0;
    }
    return s_pstOSThreadObject->pfOSThreadGetStackSpace(thread_id);
}
 
/// Change priority of a thread.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \param[in]     priority      new priority value for the thread function.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadSetPriority (osThreadId_t thread_id, osPriority_t priority)
{
    if (!s_pstOSThreadObject)
    {
        return osError;
    }

    if (!s_pstOSThreadObject->pfOSThreadSetPriority)
    {
        return osOK;
    }

    return s_pstOSThreadObject->pfOSThreadSetPriority(thread_id, priority);
}
 
/// Get current priority of a thread.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return current priority value of the specified thread.
osPriority_t osThreadGetPriority (osThreadId_t thread_id)
{
    if (!s_pstOSThreadObject || !s_pstOSThreadObject->pfOSThreadGetPriority)
    {
        return osPriorityNone;
    }
    return s_pstOSThreadObject->pfOSThreadGetPriority(thread_id);
}
 
/// Pass control to next thread that is in state \b READY.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadYield (void)
{
    if (!s_pstOSThreadObject)
    {
        return osError;
    }

    if (!s_pstOSThreadObject->pfOSThreadYield)
    {
        return osOK;
    }

    return s_pstOSThreadObject->pfOSThreadYield();
}
 
/// Suspend execution of a thread.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadSuspend (osThreadId_t thread_id)
{
    if (!s_pstOSThreadObject)
    {
        return osError;
    }

    if (!s_pstOSThreadObject->pfOSThreadSuspend)
    {
        return osOK;
    }

    return s_pstOSThreadObject->pfOSThreadSuspend(thread_id);
}
 
/// Resume execution of a thread.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadResume (osThreadId_t thread_id)
{
    if (!s_pstOSThreadObject)
    {
        return osError;
    }

    if (!s_pstOSThreadObject->pfOSThreadResume)
    {
        return osOK;
    }

    return s_pstOSThreadObject->pfOSThreadResume(thread_id);
}
 
/// Detach a thread (thread storage can be reclaimed when thread terminates).
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadDetach (osThreadId_t thread_id)
{
    if (!s_pstOSThreadObject)
    {
        return osError;
    }

    if (!s_pstOSThreadObject->pfOSThreadDetach)
    {
        return osOK;
    }

    return s_pstOSThreadObject->pfOSThreadDetach(thread_id);
}
 
/// Wait for specified thread to terminate.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadJoin (osThreadId_t thread_id)
{
    if (!s_pstOSThreadObject)
    {
        return osError;
    }

    if (!s_pstOSThreadObject->pfOSThreadJoin)
    {
        return osOK;
    }

    return s_pstOSThreadObject->pfOSThreadJoin(thread_id);
}
 
/// Terminate execution of current running thread.
void osThreadExit (void)
{
    if (!s_pstOSThreadObject || !s_pstOSThreadObject->pfOSThreadExit)
    {
        return;
    }
    s_pstOSThreadObject->pfOSThreadExit();
}
 
/// Terminate execution of a thread.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadTerminate (osThreadId_t thread_id)
{
    if (!s_pstOSThreadObject)
    {
        return osError;
    }

    if (!s_pstOSThreadObject->pfOSThreadTerminate)
    {
        return osOK;
    }

    return s_pstOSThreadObject->pfOSThreadTerminate(thread_id);
}
 
/// Get number of active threads.
/// \return number of active threads.
uint32_t osThreadGetCount (void)
{
    if (!s_pstOSThreadObject || !s_pstOSThreadObject->pfOSThreadGetCount)
    {
        return 0;
    }
    return s_pstOSThreadObject->pfOSThreadGetCount();
}
 
/// Enumerate active threads.
/// \param[out]    thread_array  pointer to array for retrieving thread IDs.
/// \param[in]     array_items   maximum number of items in array for retrieving thread IDs.
/// \return number of enumerated threads.
uint32_t osThreadEnumerate (osThreadId_t *thread_array, uint32_t array_items)
{
    if (!s_pstOSThreadObject || !s_pstOSThreadObject->pfOSThreadEnumerate)
    {
        return 0;
    }
    return s_pstOSThreadObject->pfOSThreadEnumerate(thread_array, array_items);
}


/************************************** The End Of File **************************************/

